package org.tech4j.edi.base.threadpool;

import org.tech4j.common.concurrent.threadpool.MemorySafeTaskQueue;
import org.tech4j.common.concurrent.threadpool.ResizeLinkedBlockingQueue;
import org.tech4j.common.concurrent.threadpool.Tech4jThreadFactory;
import org.tech4j.common.concurrent.threadpool.Tech4jThreadPoolExecutor;
import org.tech4j.edi.base.config.RetryPoolConfig;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @program: tech4j
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/7 15:48
 **/
public class RetryThreadPoolFactory {

    private static ThreadPoolExecutor threadPoolExecutor;

    private static final RetryPoolConfig DEFAULT_CONFIG = new RetryPoolConfig();

    /**
     * The maximum free memory reserved by the blocking queue for the JVM.
     */
    static int THE_256_MB = 256 * 1024 * 1024;

    /**
     * 默认队列大小 1000
     */
    static final Integer DEFAULT_QUEUE_SIZE = Integer.MAX_VALUE;


    private RetryThreadPoolFactory() {
    }

    /**
     * 慢线程处理
     */
    public static ThreadPoolExecutor retrySlowThreadPool = new ThreadPoolExecutor(
            10,
            20,
            60L,
            TimeUnit.SECONDS,
            new ResizeLinkedBlockingQueue<>(DEFAULT_QUEUE_SIZE),
            r -> new Thread(r, "retrySlowThread-" + r.hashCode()),
            new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 快线程处理
     */
    public static ThreadPoolExecutor retryFastThreadPool = new ThreadPoolExecutor(
            10,
            20,
            60L,
            TimeUnit.SECONDS,
            new ResizeLinkedBlockingQueue<>(DEFAULT_QUEUE_SIZE),
            r -> new Thread(r, "retryFastThread-" + r.hashCode()),
            new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 创建重试线程池
     * @param retryPoolConfig
     * @return
     */
    public synchronized static ThreadPoolExecutor createRetryThreadPool(RetryPoolConfig retryPoolConfig) {
        if (threadPoolExecutor != null) {
            return threadPoolExecutor;
        }
        Integer corePoolSize = retryPoolConfig.getCorePoolSize();
        Integer maximumPoolSize = retryPoolConfig.getMaximumPoolSize();
        Long keepAliveTime = retryPoolConfig.getKeepAliveTime();
        threadPoolExecutor =  new Tech4jThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                TimeUnit.MILLISECONDS, new MemorySafeTaskQueue<>(THE_256_MB),
                Tech4jThreadFactory.create(retryPoolConfig.getPrefix(), true),
                new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    public static ThreadPoolExecutor getThreadPoolExecutor() {
        return threadPoolExecutor == null ? createRetryThreadPool(DEFAULT_CONFIG) : threadPoolExecutor;
    }


}
